"""
验证工具
提供通用的请求数据验证功能
"""
from functools import wraps
from flask import request, current_app
from marshmallow import ValidationError
from app.utils.responses import validation_error


def validate_with(schema_cls, **kwargs):
    """
    使用Schema验证请求数据的装饰器
    
    参数:
        schema_cls: Marshmallow Schema类
        **kwargs: 传递给Schema的额外参数
    
    返回:
        装饰器函数
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kws):
            schema = schema_cls(**kwargs)
            
            try:
                # 根据请求方法确定待验证的数据
                if request.method in ('POST', 'PUT', 'PATCH'):
                    if request.is_json:
                        data = request.json
                    else:
                        # 尝试处理表单数据
                        data = request.form.to_dict()
                        
                        # 处理文件上传
                        if request.files:
                            for key, file in request.files.items():
                                data[key] = file
                else:
                    # 处理GET, DELETE等请求参数
                    data = request.args.to_dict()
                
                # 执行验证
                validated_data = schema.load(data)
                
                # 将验证后的数据传递给被装饰的函数
                kws['validated_data'] = validated_data
                
            except ValidationError as err:
                current_app.logger.warning(f"数据验证错误: {err.messages}")
                return validation_error(err.messages)
            
            return f(*args, **kws)
        return decorated_function
    return decorator


def required_params(*params):
    """
    检查必需的查询参数的装饰器
    
    参数:
        *params: 必需的参数名称
    
    返回:
        装饰器函数
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            missing = [param for param in params if param not in request.args]
            if missing:
                current_app.logger.warning(f"缺少必需的参数: {missing}")
                return validation_error({param: ['此参数是必需的'] for param in missing})
            return f(*args, **kwargs)
        return decorated_function
    return decorator


def paginate(default_page=1, default_per_page=10, max_per_page=100):
    """
    处理分页参数的装饰器
    
    参数:
        default_page: 默认页码
        default_per_page: 默认每页记录数
        max_per_page: 最大每页记录数
    
    返回:
        装饰器函数
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 获取分页参数
            try:
                page = int(request.args.get('page', default_page))
                per_page = min(int(request.args.get('per_page', default_per_page)), max_per_page)
                
                # 确保参数有效
                page = max(1, page)
                per_page = max(1, per_page)
            except ValueError:
                current_app.logger.warning("分页参数无效")
                return validation_error({
                    'page': ['页码必须是一个有效的整数'],
                    'per_page': ['每页记录数必须是一个有效的整数']
                })
            
            # 将分页参数传递给被装饰的函数
            kwargs['pagination'] = {
                'page': page,
                'per_page': per_page,
                'offset': (page - 1) * per_page,
                'limit': per_page
            }
            
            return f(*args, **kwargs)
        return decorated_function
    return decorator

EMAIL_REGEX = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')

def validate_email(email):
    """验证邮箱格式"""
    if not EMAIL_REGEX.match(email):
        raise ValidationError('无效的邮箱格式')

def validate_phone(phone):
    """验证手机号格式"""
    pattern = r'^1[3-9]\d{9}$'  # 简单的中国手机号验证规则
    if not re.match(pattern, phone):
        raise ValidationError('无效的手机号格式')

def validate_password(password):
    """验证密码强度"""
    if len(password) < 8:
        raise ValidationError('密码长度至少为8位')
    if not any(char.isdigit() for char in password):
        raise ValidationError('密码必须包含至少一个数字')
    if not any(char.isupper() for char in password):
        raise ValidationError('密码必须包含至少一个大写字母')
    if not any(char.islower() for char in password):
        raise ValidationError('密码必须包含至少一个小写字母') 